// ==UserScript==
// @name         🚀🚀🚀搜题小帮手｜查题｜大学｜成人本科｜继续教育｜复制搜题｜截图搜题｜无侵入，更安全｜超全题库，方便快捷，一步到位
// @version      0.1
// @description  搜题小帮手、查题，中学、大学试题，成人本科，继续教育，复制搜题，截图搜题，无侵入，更安全，超全题库，方便快捷，一步到位，超全题库，方便使用，辅助您一步搜题，快速搜答案，并且支持图片搜题，解决您搜题难的问题
// @author       soti
// @match        *://*/*
// @icon         
// @require      https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.16/vue.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/quill/1.3.7/quill.min.js
// @resource     snow https://cdnjs.cloudflare.com/ajax/libs/quill/1.3.7/quill.snow.min.css
// @grant        GM_info
// @grant        GM_xmlhttpRequest
// @grant        GM_getResourceText
// @grant        GM_addStyle
// @connect      appwk.baidu.com
// @connect      studypro.club
// @grant        GM_setValue
// @grant        GM_getValue
// @antifeature  ads      脚本包含搜索文本时，附带的广告
// @antifeature  payment  脚本题目搜索，需对接第三方接口付费
// ==/UserScript==
$(document).ready(function() {

  if (window.self !== window.top) {
    return;
  }

  // Tab 组件
  Vue.component('eb-tab', {
    data: function () {
      return {
        tabList: [
          { name: '搜题'}
        ],
        currentIndex: 0
      }
    },
    template: `
      <div class="eb-tab-container">
        <div v-for="(tab, idx) in tabList" class="eb-tab" v-bind:class="{ active:  currentIndex == idx }" @click="switchTab(idx)">{{tab.name}}</div>
      </div>
    `,
    methods: {
      switchTab(idx) {
        this.currentIndex = idx;
        this.$emit('switch-tab', idx);
      }
    }
  });

  // Header
  Vue.component('eb-header', {
    template:  `
      <div id="ebMyHeader" class="eb-header">
        <div>搜题小帮手</div>
        <div class="eb-close-icon" @click="closeEv">X</div>
      </div>
    `,
    mounted() {
      this.makeDraggable(this.state, document.getElementById(this.draggleId),  document.getElementById(this.targetId));
    },
    data: function() {
      return {
        draggleId: 'ebMyHeader',
        targetId: 'ebsooWrap0104',
        state: {
          dragging: false,
          initX: 0,
          initY: 0,
          transX: 0,
          transY: 0,
          moveX: 0,
          moveY: 0,
        }
      }
    },
    methods: {
      
      closeEv() {
        ebToggleOpenClose();
      },

      makeDraggable(state, el, target) {
        function globalMousemove(event) {
          const { clientX, clientY } = event;
          const { initX, initY, transX, transY } = state;
          const moveX = clientX - initX;
          const moveY = clientY - initY;
          target.style.transform = `translate(${transX + moveX}px, ${transY + moveY}px)`;
          state.moveX = moveX;
          state.moveY = moveY;
          state.dragging = true;
        }

        function globalMouseup(_event) {
          const { transX, transY, moveX, moveY } = state;
          state.transX = transX + moveX;
          state.transY = transY + moveY;
          state.moveX = 0;
          state.moveYY = 0;
          document.removeEventListener('mousemove', globalMousemove);
          document.removeEventListener('mouseup', globalMouseup);
          state.dragging = null;
        }

        function mousedown(event) {
          const {clientX, clientY} = event;
          state.initX = clientX;
          state.initY = clientY;
          document.addEventListener('mousemove', globalMousemove);
          document.addEventListener('mouseup', globalMouseup);
        }

        el.addEventListener('mousedown', mousedown);
      }
    }
  });

  // 搜索
  Vue.component('eb-content-search', {
    template: `
      <div class="eb-content-search-container">
      <span style="margin-left:15px;">手机号：<input placeholder="请输入手机号" id="phone" v-model="phone"/></span>
        <div class="eb-editor-outer">
          <div id="eb-editor-container" @keydown.enter="handleEnterKey" ></div>
          <div class="eb-my-footer">
            <div class="eb-btn primary" @click="submit">搜索</div>
            <div class="eb-btn bordered" @click="clear">清空</div>
          </div>
        </div>
        <div id="adkfuasdgku" class="eb-answers">
          <div class="fk-item" v-for="(item, index) in dataList">
            <div class="eb-question" v-html="item.question">{{index}}</div>
            
            <div class="eb-answer-wrap" v-if="item.answer.length">
              <div class="eb-label">答案：</div>
              <div class="fk-answer"  v-html="item.answer">
              </div>
            </div>
            <div class="eb-answer-wrap" v-if="item.analysis">
              <div class="eb-label">解析：</div>
              <div class="fk-analysis"  v-html="item.analysis">
              </div>
            </div>
          </div>
        </div>
        <eb-loading v-show="showLoading"></eb-loading>
      </div>
    `,
    data: function() {
      return {
        showLoading: false,
        dataList: [],
        phone:GM_getValue("phone")? GM_getValue("phone"):''
      }
    },

    methods: {
      submit() {

        let ops = quill.getContents().ops;
        let imgNode = ops.find(item => item.insert && item.insert.image);
        let txtNode = ops.find(item => item.insert && typeof item.insert == 'string');
        let question = '';
        if (imgNode) {
          let base64 = imgNode.insert.image;
          this.imgHandle(base64).then(res => {
            this.imgOcr(res).then(val => {
              this.fetchAnswer(val);
            })
          })
        } else if (txtNode) {
          question = txtNode.insert.replace(/\n|\t/g, '');
          this.fetchAnswer(question);
        }
      },
        handleEnterKey(event) {
            if (event.key === 'Enter') {
                this.submit();
            }
        },
      clear() {
        quill.deleteText(0, 99999);
      },

      fetchAnswer(question) {
        if (!question) {
          alert('请输入文字，或者复制截图进来');
          return;
        }

        if (question.length < 2) {
          alert(`至少输入2个字，当前值： ${question}`);
          return;
        }
        this.showLoading = false;

        let prodHost = 'http://so.studypro.club/api/search';
         GM_setValue("phone",this.phone);
         if(GM_getValue("phone")){
             this.phone = GM_getValue("phone")
         }
        fkingHttp('POST', prodHost, {
          headers: {
            "Content-Type": "application/json"
          },
          data: JSON.stringify({
              question: question,
            phone:  this.phone
          })
        }).then(response => {

          let dataList = JSON.parse(response.responseText);
            if(dataList && dataList.map){
                dataList=dataList.map((item, index) => {
            return {
            //  analysis: item.analysis,
              answer: item.answer,
           //   options: this.parseStr(item.options), //1
              question: `${index + 1}. <span class="typeStr">相似度【${(item.scores)}%】</span><br/>题目、 ${item.question}`
            }
          });
                this.dataList = dataList



            }else{
                this.dataList = [{
                    answer:dataList.answer,
                    question:question
                }]
            }

          //console.log(dataList);
          
        }).catch(_ => {
          this.showLoading = false;
          alert('出错了，请反馈');
        })
      },

      imgHandle(base64) {
        return new Promise((resolve, reject) => {
            const canvas = document.createElement("canvas");
            const context = canvas.getContext("2d");
            const image = new Image();
            image.setAttribute("crossOrigin", "Anonymous");
            image.src = base64;
            image.onload = function() {
                canvas.width = image.width;
                canvas.height = image.height;
                context.fillStyle = "#fff";
                context.fillRect(0, 0, canvas.width, canvas.height);
                context.drawImage(image, 0, 0);
                canvas.toBlob(blob => {
                    resolve(blob);
                });
            };
        });
      },
    
      imgOcr(blob) {
        return new Promise((resolve, reject) => {
            var fd = new FormData();
            fd.append("image", blob, "1.png");
            GM_xmlhttpRequest({
                url: "https://appwk.baidu.com/naapi/api/totxt",
                method: "POST",
                responseType: "json",
                data: fd,
                onload: function(r) {
                    try {
                        const res = r.response.words_result.map(item => {
                            return item.words;
                        }).join("");
                        resolve(res);
                    } catch (err) {
                        resolve("");
                    }
                }
            });
        });
      },

      parseStr(str) {
        try {
          let res = JSON.parse(str);
          if (Array.isArray(res)) {
            return res;
          }
        } catch {
          return [str];
        }
      },
      parseType(type) {
        const questionTypes = {
          0: '单选题', 1: '多选题', 2: '填空题', 3: '判断题', 4: '简答题',
          5: '名词解释', 6: '论述题', 7: '计算题', 8: '其它', 9: '分录题',
          10: '资料题', 11: '连线题', 13: '排序题', 14: '完型填空', 15: '阅读理解',
          17: '程序题', 20: '共用选项题'
        };
        return questionTypes[Number(type)] || '未知题型'
      }
    }
  });

  // 个人中心
  Vue.component('eb-content-my', {
    data: function() {
      return {

      }
    },
    methods: {}
  });

  // 设置
  Vue.component('eb-content-set', {
    template: `
      <div>eb-content-set</div>
    `,
    data: function() {
      return {

      }
    },
    methods: {}
  });

  Vue.component('eb-loading', {
    template: `
      <div class="eb-loading-wrap">
        <img class="eb-loading-icon" src="https://i.ibb.co/7jP0Lx5/5d37ba69fc9341179f10b85407c7d34f.gif" />
      </div>
    `,
    data: function() {

    },
    methods: {

    }
  });

  let httpClient = GM.xmlHttpRequest ? GM.xmlHttpRequest : (GM_xmlhttpRequest || null);

  const styleText = GM_getResourceText("snow");
  GM_addStyle(styleText);
  GM_addStyle(`
   input{
    outline-style: none ;
    border: 1px solid #ccc;
    border-radius: 3px;
    padding: 4px 10px;
    width: 160px;
    font-size: 14px;
    font-weight: 700;
    font-family: "Microsoft soft";
}
input:focus{
    border-color: #66afe9;
    outline: 0;
    -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);
    box-shadow: inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)
}
    #ebsooWrap0104 {
      padding-top: 32px;display: flex;flex-direction: column; position: fixed;top: 100px;right: 100px;width: 400px;height: 600px;background-color: #fff;z-index:9999;border: solid #198754 1px;overflow: hidden; transform: translate(-8000px, 0);
    }
    #ebsooWrap0104 div {
      margin: unset;
    }
    #ebsooWrap0104 #ebMyHeader {
      position: absolute;left: 0;top: 0;right: 0;height: 32px;padding: 0 4px 0 12px;text-align: left;background-color: #198754; line-height: 32px;cursor: move;display: flex;justify-content: space-between;  align-items: center; font-weight: bold; color: #fff; border-radius: 0px;
    }
    #ebsooWrap0104 #ebMyHeader .eb-close-icon {
      cursor: pointer;font-size: 12px;border: solid #fff 2px;border-radius: 50%;height: 24px;width: 24px;line-height: 22px;text-align: center;
    }
    #ebsooWrap0104 .router-content {
      height: calc(100% - 48px);
    }
    #ebsooWrap0104 .eb-content-search-container {
      height: 100%;display: flex;flex-direction: column;
    }
    #ebsooWrap0104 .eb-editor-outer {
      flex-shrink: 0;padding: 6px;box-shadow: 8px 8px 12px 0 #3c7cfc1f;
    }
    #ebsooWrap0104 .ql-container {
      height: 120px;
    }
    #ebsooWrap0104 .ql-toolbar {
      text-align: left;
    }
    #ebsooWrap0104 .eb-my-footer {
      display: flex; justify-content: center; align-items: center; height: 42px;line-height: 42px;border: 1px solid #ccc;border-top: none;box-sizing: border-box;text-align: center;
    }
    #ebsooWrap0104 .eb-my-footer .eb-btn {
      margin:0 4px; width: 64px; height: 32px; line-height: 31px;text-align: center; border-radius: 6px; cursor: pointer; font-size: 14px; letter-spacing: 2px;
    }
    #ebsooWrap0104 .eb-my-footer .eb-btn.primary {
      background-color: #198754; color: #fff;
    }
    #ebsooWrap0104 .eb-my-footer .eb-btn.bordered {
      border: 1px solid #212529;
    }
    #ebsooWrap0104 .eb-answers {
      flex: 1;text-align: left;overflow-y: scroll;
    }
    #ebsooWrap0104 .eb-answers .fk-item {
      padding: 10px 12px;border-bottom: solid #ccc 1px;
    }
    #ebsooWrap0104 .eb-answers .fk-item .eb-question,
    #ebsooWrap0104 .eb-options-wrap,
    #ebsooWrap0104 .eb-answer-wrap {
      font-size: 13px; line-height: 17px;
    }
    #ebsooWrap0104 .fk-answer {
      padding: 4px;border: dashed rgb(59, 146, 233) 1px;
    }
    #ebsooWrap0104 .fk-analysis {
      padding: 4px;
    }
    #ebsooWrap0104 .eb-answers em {
      color: red;font-weight: bold;font-style: normal;
    }

    #ebsooWrap0104 .eb-label {
      font-size: 14px;margin: 8px 0;width: fit-content;border-bottom: dashed #ccc 1px;font-weight: bold;
    }

    #ebsooWrap0104 .eb-panel-container {
      position: absolute;left: 0;top: -100%;width: 100%;height: 100%;z-index: 10000;transition: top .3s;background-color: rgba(0,0,0,0.35);
    }
    #ebsooWrap0104 .eb-panel-container.show {
      top: 32px;
    }
    #ebsooWrap0104 .eb-panel-wrap {
      width: 400px;height: 400px;margin: 80px auto auto; background-color: #fff; border-radius: 10px;
    }
    #ebsooWrap0104 .eb-tab-container {
      padding-left: 12px;margin: 6px 0;display: flex;height: 36px;border-bottom: solid #ccc 1px;
    }
    #ebsooWrap0104 .eb-tab-container .eb-tab {
      box-sizing: border-box;position: relative;top: 1px;width: 72px;height: 36px;line-height: 36px;text-align: center;cursor: pointer;border-bottom: solid #ccc 1px;border-top: solid #fff 1px;
    }
    #ebsooWrap0104 .eb-tab-container .eb-tab.active {
      border: solid #198754 1px;border-bottom: solid #fff 1px;border-top-left-radius: 6px;border-top-right-radius: 6px;background-color: #fff;
    }

    #ebsooWrap0104 .ql-toolbar.ql-snow {
      padding: 0;
    }
    #ebsooWrap0104 .eb-loading-wrap {
      position: absolute;left: 0;top: 0;right: 0;bottom: 0;background-color: rgba(0,0,0,0.05);text-align: center;
    }
    .eb-loading-wrap .eb-loading-icon {
      margin-top: 50%;
    }
    .eb-trigger-btn {
      position: fixed; right: 0;bottom:50%; width: 40px; height: 56px; line-height: 56px; background-color: #198754; color: #fff; cursor: pointer;border-top-left-radius:8px; border-bottom-left-radius: 10px; text-align: center; font-size: 20px; user-select: none;z-index: 99999;
    }
  `);

  var $wrap = $(`
  <div id="ebsooWrap0104">
    <eb-header></eb-header>
    <eb-tab @switch-tab="handleSwitchTab"></eb-tab>
    <div class="router-content">
      <eb-content-search v-show="currentTabIdx == 0"></eb-content-search>
      <eb-content-set v-show="currentTabIdx == 1"></eb-content-set>
    </div>
  </div>
  <div id="ebTriggerBtn" class="eb-trigger-btn">开</div>`);
  $('body').prepend($wrap);

  new Vue({
    el: '#ebsooWrap0104',
    data: {
      currentTabIdx: 0
    },
    methods: {
      handleSwitchTab(idx) {
        this.currentTabIdx = idx;
      }
    }
  });

  var quill = new Quill('#eb-editor-container', {
    modules: {
      toolbar: [
        ['image']
      ],
        keyboard: {
	bindings: {
		enter: {
			key: 13,
			handler: (range, context)=> {
				// Handle shift+b

			}
		},
	}
}
    },
    placeholder: '输入文字，复制截图，或者上传图片进来',
    theme: 'snow'
  });

  function fkingHttp (method, url, config) {
    let options = {
      timeout: 30000,
    }
    if (config) {
      Object.assign(options, config);
    }
    return new Promise((resolve, reject) => {
      httpClient(Object.assign({
        method: method,
        url: url.indexOf('http') > -1 ? url : baseUrl + url,
        onload: function(response) {
          resolve(response);
        },
        onerror: function (err) {
          reject(err);
        },
        ontimeout: function () {
          reject();
        }
      }, options));
    })
  };

  var show = false;
  $('#ebTriggerBtn').on('click', _ => {
    ebToggleOpenClose();
  })

  function ebToggleOpenClose() {
    if (show) {
      show = false;
      $('#ebsooWrap0104').css('transform', 'translate(-8000px, 0)');
      $('#ebTriggerBtn').css('background-color', '#198754');
      $('#ebTriggerBtn').html('开');
    } else {
      show = true;
      $('#ebsooWrap0104').css('transform', 'translate(0, 0)');
      $('#ebTriggerBtn').css('background-color', '#ccc');
      $('#ebTriggerBtn').html('关');
    }
  }
})